﻿using System.Numerics;
using System.Text;
/// <summary>
/// https://leetcode-cn.com/problems/add-binary/
/// </summary>
public class Solution
{
    private static readonly Dictionary<string, string> binToHex;
    private static readonly Dictionary<string, string> hexToBin;

    static Solution()
    {
        var bin = Enumerable.Range(0, 16).Select((value) => Convert.ToString(value, 2).PadLeft(4, '0'));
        var hex = Enumerable.Range(0, 16).Select((value) => Convert.ToString(value, 16));

        var zip = bin.Zip(hex);

        binToHex = zip.ToDictionary((val) => val.First, (val) => val.Second);
        hexToBin = zip.ToDictionary((val) => val.Second, (val) => val.First);
    }

    private IEnumerable<string> CutString(string s, int size)
    {
        StringBuilder stringBuilder = new StringBuilder(size);
        int i = 0;
        foreach (var c in s)
        {
            _ = stringBuilder.Append(c);
            i++;
            if (i >= size)
            {
                i = 0;
                yield return stringBuilder.ToString();
                _ = stringBuilder.Clear();
            }
        }
        if (stringBuilder.Length > 0)
            yield return stringBuilder.ToString();
    }

    public string AddBinary(string a, string b)
    {
        a = a.PadLeft((a.Length / 4 + 2) * 4, '0');
        b = b.PadLeft((b.Length / 4 + 2) * 4, '0');

        a = string.Join("", this.CutString(a, 4).Select((val) => binToHex[val]));
        b = string.Join("", this.CutString(b, 4).Select((val) => binToHex[val]));

        var aValue = BigInteger.Parse(a, System.Globalization.NumberStyles.HexNumber);
        var bValue = BigInteger.Parse(b, System.Globalization.NumberStyles.HexNumber);

        var resultValue = aValue + bValue;
        var result = resultValue.ToString("x");

        result = string.Join("", result.Select((val) => hexToBin[val.ToString()])).TrimStart('0');
        return result.Length == 0 ? "0" : result;
    }
}